/**
 * Created by Weizehua on 2017/1/20.
 */
import {Crypto as C} from "node-ts-crypto-promise";
import {Singleton} from "ts.di";
import {pbkdf2} from "crypto";
import {PermissionInfo} from "../../User/Permission";

@Singleton()
export class Hash {
    constructor(private passwordSalt,
                private digestSalt,
                private signtureSecret) {
    }

    passwordHash(data: string): Promise<string> {
        return new Promise<string>((resolve, reject) => {
            pbkdf2(data,
                Buffer.from(this.passwordSalt, 'base64'),
                100,
                64,
                'sha256',
                (error, derivedKey) => {
                    if (error) {
                        reject(error);
                    }
                    else {
                        resolve(derivedKey.toString('base64'))
                    }
                })

        });
    }

    async digestCaptcha(captcha: string, phone: string, expiredDate: Date): Promise<string> {
        return this.digest(captcha + phone + String(Number(expiredDate)));
    }

    async signCaptcha(captcha: string, expiredDate: Date): Promise<string> {
        let data = captcha + expiredDate.toUTCString();
        return this.sign(data);
    }

    async digest(data: string): Promise<string> {
        return (await C.hash(data + this.digestSalt, 'SHA256')).toString('base64');
    }

    async test(data: string, digest: string): Promise<boolean> {
        return digest === await this.digest(data);
    }

    async sign(data: string): Promise<string> {
        return (await C.hmac(data, this.signtureSecret, 'SHA256')).toString('base64');
    }

    async verify(data: string, signature: string): Promise<boolean> {
        return signature === await this.sign(data);
    }

    async signUser(id: number, permissions: PermissionInfo, expiredDate: any) {
        return this.sign(JSON.stringify([id, permissions, new Date(expiredDate).toUTCString()]));
    }

    async verifyUser(id: number, permissions: PermissionInfo, expiredDate: any, signature) {
        return this.verify(JSON.stringify([id, permissions, new Date(expiredDate).toUTCString()]), signature)
    }
}
